package cn.hiapi.publics.api;

import cn.hiapi.basic.ResponseEntity;
import cn.hiapi.basic.controller.BasicController;
import cn.hiapi.basic.jpa.pageable.QueryWrapper;
import cn.hiapi.basic.security.TokenGet;
import cn.hiapi.basic.token.Token;
import cn.hiapi.interfaces.DispatchContext;
import cn.hiapi.interfaces.system.ILocationService;
import cn.hiapi.interfaces.system.data.LocationData;
import cn.hiapi.publics.query.PublicShopQuery;
import cn.hiapi.publics.vo.ShopBaseVo;
import cn.hiapi.shop.api.platform.vo.ShopVo;
import cn.hiapi.shop.entity.shop.Shop;
import cn.hiapi.shop.entity.shop.ShopScore;
import cn.hiapi.shop.entity.shop.ShopType;
import cn.hiapi.shop.service.shop.ShopScoreService;
import cn.hiapi.shop.service.shop.ShopService;
import cn.hiapi.shop.service.shop.ShopTypeService;
import cn.hiapi.shop.service.shop.vo.ShopDistance;
import cn.hiapi.shopkeeper.entity.user.SubscribeShop;
import cn.hiapi.shopkeeper.service.user.SubscribeShopService;
import cn.hiapi.user.vo.SubscribeShopVo;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Distance;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author AdinZ
 * @date 2023/3/29 18:26
 */
@RestController("shopkeeperPublicShopController")
@RequestMapping("/public/shop")
public class PublicShopController extends BasicController {

    private final DispatchContext dispatchContext;

    public PublicShopController(DispatchContext dispatchContext) {
        this.dispatchContext = dispatchContext;
    }


    @PostMapping("/query")
    public ResponseEntity query(@RequestBody PublicShopQuery query) {
        query.setDirection(Sort.Direction.DESC);
        String method = query.getMethod();
        if (StringUtils.equalsIgnoreCase(method, "recommend")) {
            query.setProperties("sort");
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("status", 1);
            ResponseEntity<List<Shop>> r = this.dispatchContext.getServiceOne(ShopService.class).findPage(wrapper, query.getPageable());
            List<ShopBaseVo> collect = r.getData().stream().map(e -> toResult(e, null)).collect(Collectors.toList());
            return toSuccess(collect, r.getTotal(), r.getTotalPage());
        } else if (StringUtils.equalsIgnoreCase(method, "subscribe")) {
            Token<Object> token = TokenGet.get();
            if (token == null) return toSuccess(Lists.newArrayList(), 0L, 0L);
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("uid", token.getFid());
            query.setDirection(Sort.Direction.DESC);
            query.setProperties("id");
            ResponseEntity<List<SubscribeShop>> r = this.dispatchContext.getServiceOne(SubscribeShopService.class).findPage(wrapper, query.getPageable());
            List<ShopBaseVo> collect = r.getData().stream().map(e -> this.dispatchContext.getServiceOne(ShopService.class).get(e.getShopId()))
                    .map(e -> toResult(e, null))
                    .collect(Collectors.toList());
            return toSuccess(collect, r.getTotal(), r.getTotalPage());
        } else if (StringUtils.equalsIgnoreCase(method, "location")) {

            Long cityId = null;

            if (StringUtils.isNotEmpty(query.getCity())) {
                List<LocationData> locationed = this.dispatchContext.getServiceOne(ILocationService.class).locationAll();
                Optional<LocationData> optional = locationed.stream().filter(e -> StringUtils.equalsIgnoreCase(e.getLevel(), "city")).filter(e -> StringUtils.equalsIgnoreCase(e.getName(), query.getCity())).findFirst();
                if (optional.isPresent()) cityId = optional.get().getId();
            }

            ResponseEntity<List<ShopDistance>> r = this.dispatchContext.getServiceOne(ShopService.class).locationSearch(cityId,0, query.getLat(), query.getLng(), 1000000000L, query.getSize(), query.getPage());
            List<ShopBaseVo> collect = r.getData().stream().map(e -> toResult(e, e.getDistance())).collect(Collectors.toList());
            return toSuccess(collect, r.getTotal(), r.getTotalPage());
        } else return toError("method 错误");
    }


    private ShopBaseVo toResult(Shop e, Distance distance) {
        ShopBaseVo vo = e.copy(new ShopBaseVo());
        ShopScore score = this.dispatchContext.getServiceOne(ShopScoreService.class).getByShopId(0, e.getId());
        if (score != null)
            vo.setScore(score.getComplexScore());
        List<LocationData> locationDataList = this.dispatchContext.getServiceOne(ILocationService.class).locationGet(e.getStateId(), e.getCityId(), e.getDistrictId());
        StringBuffer address = new StringBuffer();
        locationDataList.forEach(b -> address.append(b.getName()).append(" "));
        address.append(e.getAddress());
        vo.setAddress(address.toString());
        ShopType type = this.dispatchContext.getServiceOne(ShopTypeService.class).get(e.getCid());
        if (type != null)
            vo.setCategory(type.getName());
        if (distance != null)
            vo.setDistance(distance.getValue());
        return vo;

    }

}
